classdef stageTwo < dynamicprops
    
    properties
        handles;
        
        originalFilterPoles;
        originalFilterZeros;
        
        auxiliarFilterPoles;
        auxiliarFilterZeros;
        
        wa;
        wp;
        wpMAS;
        wpMENOS;
        waMAS;
        waMENOS;
        w0;
        
        filterType;
        
        remainingPoles;
        remainingZeros;
        actualPoles;
        actualZeros;
        
        stageAmount;
        stageTracking;
        plotTracking;
        stageID;
        
        currentStageID;
        
        currentPlot;
        
        finalFilter;
        
    end
    
    methods
        
        %% Constructor
        function main = stageTwo(oFilterPoles, oFilterZeros, filterType, wa, wp, wpMAS, wpMENOS, waMAS, waMENOS, w0)  
        
            
           hfig = hgload('stageTWOGui.fig'); % load 'GUIDE generated' Figure.
           main.handles = guihandles(hfig); % get figure handles.
           movegui(hfig,'center');   % sets Figure position.
           
           main.finalFilter = newFilter(main);
           main.finalFilter.filterPoles = [];
           main.finalFilter.filterZeros = [];
           main.finalFilter.filterGain = 1;
           main.finalFilter.transferFunction = main.finalFilter.filterGain * tf(poly(main.finalFilter.filterZeros),poly(main.finalFilter.filterPoles));
           
           main.originalFilterPoles = oFilterPoles;
           main.originalFilterZeros = oFilterZeros;
           main.auxiliarFilterPoles = oFilterPoles;
           main.auxiliarFilterZeros = oFilterZeros;
           
           main.wa = wa;
           main.wp = wp;
           main.wpMAS = wpMAS;
           main.wpMENOS = wpMENOS;
           main.waMAS = waMAS;
           main.waMENOS = waMENOS;
           main.w0 = w0;
           
           main.filterType = filterType;
           
           main.actualPoles = 0;
           main.actualZeros = 0;
           
           main.remainingPoles = size(oFilterPoles);
           main.remainingPoles = max(main.remainingPoles);
           
           main.remainingZeros = size(oFilterZeros);
           main.remainingZeros = max(main.remainingZeros);
           
           main.stageAmount = 0;
           main.stageID = 0;  
           
           main.currentStageID = 0;
           main.currentPlot = 0;
           
           hold(main.handles.axes_pzmap);
           hold(main.handles.axes_gain);
           hold(main.handles.axes_phase);
           hold(main.handles.axes_main);
           
           stageTwoCallbacks(main);
            
        end
   
        %%
        function btn_auto_callback(main, varargin)
            
            matrix = reAgroupRoot(main.originalFilterPoles,main.originalFilterZeros);
            
            matrixSize = size(matrix);
            stagesAmount = matrixSize(1);
            
            for index = 1 : stagesAmount
                [stageTrack, stageID] = addNewStage(main);
                
                stageToEdit = ['stage' num2str(stageID)];
                main.stageTracking{index,1} = stageID;
                main.stageTracking{index, 2} = stageTrack;
                main.(stageToEdit).stageID = stageID;
                
                if matrix(index, 1) ~= Inf
                    main.(stageToEdit).stagePoles(1) = matrix(index,1);
                end
                if matrix(index, 2) ~= Inf
                    main.(stageToEdit).stagePoles(2) = matrix(index,2);
                end
                if matrix(index, 3) ~= Inf
                    main.(stageToEdit).stageZeros(1) = matrix(index,3);
                end
                if matrix(index, 4) ~= Inf
                    main.(stageToEdit).stageZeros(2) = matrix(index,4);
                end
                
                main.currentStageID = stageID;
                
                stageType = obtainStageType(main.(stageToEdit).stagePoles, main.(stageToEdit).stageZeros);

             
                main.(stageToEdit).stageTransferFunction = tf(poly(main.(stageToEdit).stageZeros),poly(main.(stageToEdit).stagePoles));
             
                addStageGain(main, stageType, main.currentStageID, main.wa, main.wp, main.w0);
                
                [gainHandle, phaseHandle, poleHandle, zeroHandle] = doFigures(main, main.(stageToEdit).stageTransferFunction);
            
                main.plotTracking{index, 1} = gainHandle; 
                main.plotTracking{index, 2} = phaseHandle;
                main.plotTracking{index, 3} = poleHandle;
                main.plotTracking{index, 4} = zeroHandle;
                    
                set(main.plotTracking{index, 1}, 'Visible', 'Off');
                set(main.plotTracking{index, 2}, 'Visible', 'Off');
                set(main.plotTracking{index, 3}, 'Visible', 'Off');
                set(main.plotTracking{index, 4}, 'Visible', 'Off');

            end
 
            main.stageAmount = stagesAmount;
            main.remainingPoles = 0;
            main.remainingZeros = 0;
            main.originalFilterPoles = [];
            main.originalFilterZeros = [];
            
            updateRemainingPolesList(main);
            updateRemainingZerosList(main);
            
            updateStageList(main);
            
            showStage(main, main.stageAmount);
            
            set(main.handles.list_stages, 'Value', main.stageAmount);
            
            setRDLoss(main);
            
            
        end
        
        %%
        function btn_addPole_callback(main, varargin)
            
            if main.actualPoles == 0 && main.remainingPoles ~= 0 && main.actualZeros == 0
                [stageTrack, stageID] = addNewStage(main);
                main.currentStageID = stageID;
                main.stageAmount = main.stageAmount + 1;
                main.stageTracking{main.stageAmount,2} = stageTrack;
            else
                stageID = main.currentStageID;
            end
            
            if main.actualPoles < 2 && main.remainingPoles > 0
                
                stageToEdit = ['stage' num2str(stageID)];   % EN que etapa se colocara.
                
                [selectedRow, poleToAdd] = getPoleToAdd(main);  % OBtiene de la GUI el polo seleccionado
                
                if main.actualPoles == 0        % LO agrega como primeor o segundo.
                    main.(stageToEdit).stagePoles(1) = poleToAdd;
                else
                    main.(stageToEdit).stagePoles(2) = poleToAdd;
                end
                
                rearrangePolesList(main, selectedRow);
                
                main.actualPoles = main.actualPoles + 1;
                
                main.remainingPoles = main.remainingPoles - 1;
                updateRemainingPolesList(main);
                updateActualPolesList(main, stageID);
                                
            end
            
        end
        
        
        %%
        function btn_addZero_callback(main, varargin)
            
            if main.actualZeros == 0 && main.remainingZeros ~= 0 && main.actualPoles==0
                [stageTrack, stageID] = addNewStage(main);
                main.currentStageID = stageID;
                main.stageAmount = main.stageAmount + 1;
                main.stageTracking{main.stageAmount,2} = stageTrack;
            else
                stageID = main.currentStageID;
            end
            
            if main.actualZeros < 2 && main.remainingZeros > 0
                
                stageToEdit = ['stage' num2str(stageID)];
                
                [selectedRow, zeroToAdd] = getZeroToAdd(main);
                
                if main.actualZeros == 0
                    main.(stageToEdit).stageZeros(1) = zeroToAdd;
                else
                    main.(stageToEdit).stageZeros(2) = zeroToAdd;
                end
                
                rearrangeZerosList(main, selectedRow);
                
                main.actualZeros = main.actualZeros + 1;
                
                main.remainingZeros = main.remainingZeros - 1;
                updateRemainingZerosList(main);
                updateActualZerosList(main, stageID);
                
            end
            
        end
        
        
        %%
        function btn_removePole_callback(main, varargin)
            
            stageToEdit = ['stage' num2str(main.currentStageID)];
                       
            if(main.actualPoles > 0)
            
                main.remainingPoles = main.remainingPoles + 1;
                selectedRow = getSelectedItem(main, 'list_actualPoles');

                main.originalFilterPoles(main.remainingPoles) = main.(stageToEdit).stagePoles(selectedRow);
                main.(stageToEdit).stagePoles(selectedRow) = [];
                main.actualPoles = main.actualPoles - 1;
                
                updateRemainingPolesList(main);
                updateActualPolesList(main, main.currentStageID);
                
                if main.actualPoles == 0 && main.actualZeros == 0
                    delete(main.stageTracking{main.stageAmount, 2});
                    main.stageID = main.stageID - 1;
                end
                
            end
            
            
        end
        
        
        %%
        function btn_removeZero_callback(main, varargin)
            
            stageToEdit = ['stage' num2str(main.currentStageID)];
                       
            if(main.actualZeros > 0)
            
                main.remainingZeros = main.remainingZeros + 1;
                selectedRow = getSelectedItem(main, 'list_actualZeros');

                main.originalFilterZeros(main.remainingZeros) = main.(stageToEdit).stageZeros(selectedRow);
                main.(stageToEdit).stageZeros(selectedRow) = [];
                main.actualZeros = main.actualZeros - 1;
                
                updateRemainingZerosList(main);
                updateActualZerosList(main, main.currentStageID);
                
                if main.actualPoles == 0 && main.actualZeros == 0
                    delete(main.stageTracking{main.stageAmount, 2});
                    main.stageID = main.stageID - 1;
                end
                
            end
            
        end
        
        
        %%
        function btn_create_callback(main, varargin)
            
            stageToEdit = ['stage' num2str(main.currentStageID)];
           
            main.stageTracking{main.stageAmount, 1} = main.currentStageID;
            
            stageType = obtainStageType(main.(stageToEdit).stagePoles, main.(stageToEdit).stageZeros);

            main.(stageToEdit).stageTransferFunction = tf(poly(main.(stageToEdit).stageZeros),poly(main.(stageToEdit).stagePoles));
             
            addStageGain(main, stageType, main.currentStageID, main.wa, main.wp, main.w0);
            
            main.actualZeros = 0;
            main.actualPoles = 0;
            
            updateActualPolesList(main, main.currentStageID);
            updateActualZerosList(main, main.currentStageID);
            
            setRDLoss(main);
            
            updateStageList(main);
            
            %updateFinalFilter(main, );
            
            % Aca plotea
            [gainHandle, phaseHandle, poleHandle, zeroHandle] = doFigures(main, main.(stageToEdit).stageTransferFunction);
            
            main.plotTracking{main.stageAmount, 1} = gainHandle; 
            main.plotTracking{main.stageAmount, 2} = phaseHandle;
            main.plotTracking{main.stageAmount, 3} = poleHandle;
            main.plotTracking{main.stageAmount, 4} = zeroHandle;
            
            
            showStage(main, main.stageAmount);
            
        end
        
        
        %%
        function btn_delete_callback(main, varargin)
        
            selectedRow = getSelectedItem(main, 'list_stages');
            
            main.stageAmount = main.stageAmount-1;
                        
            stageToReturn = ['stage' num2str(main.stageTracking{selectedRow,1})];
                
            stagePolesAmount = max(size(main.(stageToReturn).stagePoles));
            stageZerosAmount = max(size(main.(stageToReturn).stageZeros));
            
            if stagePolesAmount > 0
                for index = 1:stagePolesAmount
                    main.remainingPoles = main.remainingPoles + 1;
                    main.originalFilterPoles(main.remainingPoles) = main.(stageToReturn).stagePoles(index);
                end
            end
            
            updateRemainingPolesList(main);
           
            if stageZerosAmount > 0
                for index = 1:stageZerosAmount
                    main.remainingZeros = main.remainingZeros + 1;
                    main.originalFilterZeros(main.remainingZeros) = main.(stageToReturn).stageZeros(index);
                end
            end
            
            updateRemainingZerosList(main);
            
            delete(main.stageTracking{selectedRow, 2});
            
            
            for index = selectedRow : main.stageAmount
                main.stageTracking{index,1} = main.stageTracking{index+1,1};
                main.stageTracking{index,2} = main.stageTracking{index+1,2};
            end
            
            
            updateStageList(main);
            
            
        end
        
        
        %%
        function btn_plotAll_callback(main, varargin)
            main.finalFilter.transferFunction = main.finalFilter.filterGain * tf(1);
            
            for index = 1 : main.stageAmount
                stage = ['stage' num2str(main.stageTracking{index,1})];
                main.finalFilter.transferFunction = main.finalFilter.transferFunction * main.(stage).stageTransferFunction;
            end
            figure();
            bode(main.finalFilter.transferFunction);
        end
        
        
        %%
        function btn_plotStage_callback(main, varargin)
            
            selectedRow = getSelectedItem(main, 'list_stages');
            
            showStage(main, selectedRow);
            
        end
        
               
        
        %%
        function btn_stageUp_callback(main, varargin)
            
            selectedRow = getSelectedItem(main, 'list_stages');
            
            if selectedRow == 1
                %error
            else
                aux1 = main.stageTracking{selectedRow, 1};
                aux2 = main.stageTracking{selectedRow, 2};
                aux3 = main.plotTracking{selectedRow,1};
                aux4 = main.plotTracking{selectedRow,2};
                aux5 = main.plotTracking{selectedRow,3};
                aux6 = main.plotTracking{selectedRow,4};
                
                main.stageTracking{selectedRow,1} = main.stageTracking{selectedRow-1,1};
                main.stageTracking{selectedRow,2} = main.stageTracking{selectedRow-1,2};
                
                main.plotTracking{selectedRow,1}= main.plotTracking{selectedRow-1,1};
                main.plotTracking{selectedRow,2}= main.plotTracking{selectedRow-1,2};
                main.plotTracking{selectedRow,3}= main.plotTracking{selectedRow-1,3};
                main.plotTracking{selectedRow,4}= main.plotTracking{selectedRow-1,4};
                
                main.stageTracking{selectedRow-1,1} = aux1;
                main.stageTracking{selectedRow-1,2} = aux2;
                main.plotTracking{selectedRow-1,1} = aux3;
                main.plotTracking{selectedRow-1,2} = aux4;
                main.plotTracking{selectedRow-1,3} = aux5;
                main.plotTracking{selectedRow-1,4} = aux6;
                
            end
                      
            
            setRDLoss(main);
            
            updateStageList(main);

            
        end
        
        %%
        function btn_stageDown_callback(main, varargin)
            selectedRow = getSelectedItem(main, 'list_stages');
            
            if selectedRow == main.stageAmount
                %error
            else
                
%                 aux1 = main.stageTracking{selectedRow, 1};
%                 aux2 = main.stageTracking{selectedRow, 2};
%                 main.stageTracking{selectedRow,1} = main.stageTracking{selectedRow+1,1};
%                 main.stageTracking{selectedRow,2} = main.stageTracking{selectedRow+1,2};
%                 
%                 main.stageTracking{selectedRow+1,1} = aux1;
%                 main.stageTracking{selectedRow+1,2} = aux2;
                
                aux1 = main.stageTracking{selectedRow, 1};
                aux2 = main.stageTracking{selectedRow, 2};
                aux3 = main.plotTracking{selectedRow,1};
                aux4 = main.plotTracking{selectedRow,2};
                aux5 = main.plotTracking{selectedRow,3};
                aux6 = main.plotTracking{selectedRow,4};
                
                main.stageTracking{selectedRow,1} = main.stageTracking{selectedRow+1,1};
                main.stageTracking{selectedRow,2} = main.stageTracking{selectedRow+1,2};
                
                main.plotTracking{selectedRow,1}= main.plotTracking{selectedRow+1,1};
                main.plotTracking{selectedRow,2}= main.plotTracking{selectedRow+1,2};
                main.plotTracking{selectedRow,3}= main.plotTracking{selectedRow+1,3};
                main.plotTracking{selectedRow,4}= main.plotTracking{selectedRow+1,4};
                
                main.stageTracking{selectedRow+1,1} = aux1;
                main.stageTracking{selectedRow+1,2} = aux2;
                main.plotTracking{selectedRow+1,1} = aux3;
                main.plotTracking{selectedRow+1,2} = aux4;
                main.plotTracking{selectedRow+1,3} = aux5;
                main.plotTracking{selectedRow+1,4} = aux6;

            end

                        
            setRDLoss(main);
            
            updateStageList(main);
        end
        
        %%
        function btn_zoom_callback(main, varargin)
            
            zoom();
        end
        
        %%
        function btn_pan_callback(main, varargin)
            
            pan();
        end
        
        %%
        function btn_grid_callback(main, varargin)
            
            grid(main.handles.axes_main);
        end
        
        %%
        function btn_track_callback(main, varargin)
           
           datacursormode();
           
       end
        
        %%
        function btn_modGain_callback(main, varargin)
            
            switch get(get(main.handles.radioGroup_units,'SelectedObject'),'Tag')
                case 'radio_dB'
                    KtoAdd = str2num(get(main.handles.txt_gain, 'String'));
                    KtoAdd = 10^(KtoAdd/20);
                case 'radio_times'
                    KtoAdd = str2num(get(main.handles.txt_gain, 'String'));
            end
            
            switch get(get(main.handles.radioGroup_whereTo,'SelectedObject'),'Tag')
                case 'radio_stage'
                    selectedRow = getSelectedItem(main, 'list_stages');
                    stage = ['stage' num2str(main.stageTracking{selectedRow,1})];
                    main.(stage).stageTransferFunction = main.(stage).stageTransferFunction * KtoAdd;
                    main.(stage).stageGain = main.(stage).stageGain * KtoAdd;
                    
                    [gainHandle, phaseHandle, poleHandle, zeroHandle] = doFigures(main, main.(stage).stageTransferFunction);
                    
                    delete(main.plotTracking{selectedRow, 1});
                    main.plotTracking{selectedRow, 1} = gainHandle; 
                    delete(main.plotTracking{selectedRow, 2});
                    main.plotTracking{selectedRow, 2} = phaseHandle;
                    delete(main.plotTracking{selectedRow, 3});
                    main.plotTracking{selectedRow, 3} = poleHandle;
                    delete(main.plotTracking{selectedRow, 4});
                    main.plotTracking{selectedRow, 4} = zeroHandle;
                    
                    showStage(main, selectedRow);
                    
                case 'radio_filter'
                    
                    main.finalFilter.transferFunction = tf(1);
            
                    for index = 1 : main.stageAmount
                        stage = ['stage' num2str(main.stageTracking{index,1})];
                        main.finalFilter.transferFunction = main.finalFilter.transferFunction * main.(stage).stageTransferFunction;
                    end
                                       
                    oldGain = 20*log10(main.finalFilter.filterGain);
                    newGain = oldGain + 20*log10(KtoAdd);
                    main.finalFilter.filterGain = 10^(newGain/20);
                    main.finalFilter.transferFunction = main.finalFilter.transferFunction* main.finalFilter.filterGain;
                    
                    
            end
            
           
            
        end
        
        %%
        function btn_minRD_callback(main, varargin)
            
            [dinamicTotal, bestStageTracking]=bestDinamicRange(main, main.filterType, main.wa, main.wp, main.waMAS, main.waMENOS, main.wpMAS, main.wpMENOS);
            
            updateStageList(main);
            setRDLoss(main);
            
        end
        
        %%
        function axes_gain_callback(main, varargin)
            
            cla(main.handles.axes_main);
            
            for index = 1: main.stageAmount
            
            copyobj(main.plotTracking{index,1}, main.handles.axes_main);
            
            set(main.handles.axes_main, 'XScale', 'log');
            
            end
        end
        
        %%
        function axes_phase_callback(main, varargin)
            
            cla(main.handles.axes_main);
            
            for index = 1: main.stageAmount
            
            copyobj(main.plotTracking{index,2}, main.handles.axes_main);
            
            end
            
            set(main.handles.axes_main, 'XScale', 'log');
            
        end
        
        %%
        function axes_pzmap_callback(main, varargin)
            
            cla(main.handles.axes_main);
            
            
            for index = 1: main.stageAmount
            
            copyobj(main.plotTracking{index,3}, main.handles.axes_main);
            copyobj(main.plotTracking{index,4}, main.handles.axes_main);
            
            
            end
            
            set(main.handles.axes_main, 'XScale', 'linear');
            
        end
        
        
        
    end
end